package com.tbit.uqbike.service.base.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.common.entity.view.Result;
import com.tbit.maintain.api.MachineApi;
import com.tbit.uqbike.constant.BikeStateConstant;
import com.tbit.uqbike.constant.MachineFunctionConstant;
import com.tbit.uqbike.constant.MapConstant;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.*;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.bo.BatchMoveMachineBO;
import com.tbit.uqbike.object.pojo.dto.MachineRemindDTO;
import com.tbit.uqbike.object.pojo.dto.MachineSearchDTO;
import com.tbit.uqbike.object.pojo.vo.BatchMoveMachineReqVO;
import com.tbit.uqbike.object.pojo.vo.BatchOperationMsgVO;
import com.tbit.uqbike.object.pojo.vo.RemindStateVO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.base.CalibrateService;
import com.tbit.uqbike.service.base.MachineService;
import com.tbit.uqbike.service.base.TokenService;
import com.tbit.uqbike.service.business.CodeChangeLogService;
import com.tbit.uqbike.service.business.MachineOccupyService;
import com.tbit.uqbike.service.business.MannedService;
import com.tbit.uqbike.service.business.machine.event.MachineDeleteEvent;
import com.tbit.uqbike.service.rpcservice.MachineBorrowService;
import com.tbit.uqbike.service.rpcservice.MachineStatusService;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.webmanager.business.machine_op_log.annotation.InsertMachineOpLog;
import com.tbit.uqbike.webmanager.business.machine_op_log.aspect.MachineOpLogDetailHolder;
import com.tbit.uqbike.webmanager.business.machine_op_log.service.MachineOpLogService;
import com.tbit.uqbike.webmanager.controller.BaseController;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.dao.log.RecoveryLogMapper;
import com.tbit.uqbike.webmanager.req.machine.QueryByPointReq;
import com.tbit.uqbike.webmanager.util.GeoUtil;
import com.tbit.uqbike.webmanager.util.ListUtil;
import com.tbit.uqbike.webmanager.util.StringUtil;
import com.tbit.uqbike.webmanager.util.StringUtils;
import com.tbit.uqbike.webmanager.util.http.rpc.UQHttpMain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tbit.uqbike.constant.MachineFunctionConstant.FUNCTION_NAME_MAP;

/**
 * @author chenmengran
 * @Description: 设备
 * @date 2019\12\12 001215:23
 */
@Service
@Slf4j
public class MachineServiceImpl implements MachineService {
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private MachineApi machineApi;
    @Autowired
    private PurviewService purviewService;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private BatteryModelDao batteryModelDao;
    @Autowired
    private CodeChangeLogService codeChangeLogService;
    @Autowired
    private AccountUserDao accountUserDao;
    @Autowired
    private HolderAccountBoundDao holderAccountBoundDao;
    @Autowired
    private RoleDao roleDao;
    @Resource
    private GeoReMachineDao georeMachineDao;
    @Autowired
    private MachineFunctionDao machineFunctionDao;
    @Autowired
    private StockMachineMapper stockMachineMapper;
    @Autowired
    private DetentionMachineBoundMapper detentionMachineBoundMapper;
    @Autowired
    private MachineStatusService machineStatusService;

    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private RecoveryLogMapper recoveryLogMapper;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private MachineOccupyService machineOccupyService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private MannedService mannedService;
    @Autowired
    private MachineOpLogService machineOpLogService;

    private void purviewCheck(LoginInfo info, Integer accountId) {
        Account opAcc = accountDao.getByAccountId(info.id);
        Account obj = accountDao.getByAccountId(accountId);
        if (null == obj || !Objects.equals(obj.getType(), UserConstant.USER_AGENT)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        if (!purviewService.purviewCheck(opAcc, obj)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
    }

    @Override
    public Machine getByMachineNO(String machineNO) {
        return machineDao.getByMachineNO(machineNO);
    }

    @Override
    public Machine getByMachineId(Integer machineId) {
        return machineDao.getByMachineId(machineId);
    }

    @Override
    public List<Machine> getByMachineNOs(List<String> machineNOs) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("machineNOs", StringUtil.getArrayListString(machineNOs));

        return machineDao.getByMachineNOs(params);
    }

    @Override
    public List<Machine> getByAccountIdAndMachineNOs(List<Integer> accountIds, List<String> machineNOs) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("accountIds", accountIds);
        params.put("machineNOs", StringUtil.getArrayListString(machineNOs));

        return machineDao.getByAccountIdAndMachineNOs(params);
    }

    @Override
    //@Transactional
    public void addMachine(LoginInfo info, List<MachineImportInfo> machineInfoList, Integer machineType,
                           Integer accountId, Integer batteryModelId, Integer secondaryBattertId, Integer[] functionList) {
        purviewCheck(info, accountId);
        BatteryModel batteryModel = batteryModelDao.getByBatteryModelId(batteryModelId);
        if (null == batteryModel) {
            throw new BaseException(SystemCodeEnum.BATTERYMODEL_NOT_VALID);
        }
        if (machineType == null) {
            machineType = 0;
        }
        batAddMachine(machineInfoList, machineType, accountId, batteryModelId, secondaryBattertId, functionList);
    }

    public void batAddMachine(List<MachineImportInfo> machineInfoList, Integer machineType, Integer accountId,
                              Integer batteryModelId, Integer secondaryBattertId, Integer[] functionList) {
        List<String> mnoList = machineDeduplication(machineInfoList, 0);
        // 批量插入
        Map<String, Object> map = new HashMap<>();
        map.put("infos", machineInfoList);
        map.put("accountId", accountId);
        map.put("machineType", machineType);
        machineDao.batInsertMachine(map);
        // 查询回id绑定电池方案
        List<Integer> machineIds = machineDao.getMachineIdByMnos(mnoList);
        map.put("list", machineIds);
        map.put("batteryModelId", batteryModelId);
        map.put("secondaryBattertId", secondaryBattertId);
        batteryModelDao.batBoundByMachineId(map);


        // 插入车辆操作日志
        machineOpLogService.batchAddRecord("车辆录入", "添加", true, null, machineDao.getByMachineIdS(machineIds));
        Map<Integer, Machine> machineMap = machineDao.getByMachineIdS(machineIds).stream()
                .collect(Collectors.toMap(Machine::getMachineId, Function.identity()));

        //设备功能配置
        final Date updateTime = new Date();
        if (functionList != null) {
            List<MachineFunction> functions = Arrays.stream(functionList)
                    .flatMap(functionType -> machineIds.stream().map(machineId -> {
                        MachineFunction machineFunction = new MachineFunction();
                        machineFunction.setFunctionName(FUNCTION_NAME_MAP.get(functionType));
                        machineFunction.setFunctionType(functionType);
                        machineFunction.setFunctionValue(1);
                        machineFunction.setMachineId(machineId);
                        machineFunction.setUpdateTime(updateTime);
                        return machineFunction;
                    })).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(functions)) {
                machineFunctionDao.addBatch(functions);
            }
            if (Arrays.asList(functionList).contains(MachineFunctionConstant.MACHINE_TYPE_RULE_RIDE)) {
                List<Camera> cameraList = mnoList.stream().map(x -> new Camera(accountId, x, null, updateTime)).collect(Collectors.toList());
                machineFunctionDao.addCameraBatch(cameraList);
            }
            // 插入车辆操作日志-功能配置
            UserInfo info = BaseController.fetchUserInfo();
            List<MachineOpLog> machineOpLogs = functions.stream()
                    .map(x -> MachineOpLog.builder()
                            .accountId(accountId)
                            .machineId(x.getMachineId())
                            .userCode(machineMap.get(x.getMachineId()).getUserCode())
                            .machineNO(machineMap.get(x.getMachineId()).getMachineNO())
                            .operation("功能配置-" + FUNCTION_NAME_MAP.get(x.getFunctionType()))
                            .opType("添加")
                            .opUser(info.getName())
                            .opUserPhone(info.getPhone())
                            .opPlatform(OperationPlatform.MANAGER.code)
                            .result(true)
                            .build())
                    .collect(Collectors.toList());
            machineOpLogService.insertBatch(machineOpLogs);
        }
    }

    public void machineCheck(MachineImportInfo item) {
        if (item.userCode != null && item.userCode.length() >= 25) {
            throw new BaseException(SystemCodeEnum.MACHINE_OUT_OF_LENGTH);
        }
        if (item.machineNO != null && item.machineNO.length() >= 25) {
            throw new BaseException(SystemCodeEnum.MACHINE_OUT_OF_LENGTH);
        }
        if (item.frame != null && item.frame.length() >= 25) {
            throw new BaseException(SystemCodeEnum.MACHINE_OUT_OF_LENGTH);
        }
        if (item.license != null && item.license.length() >= 25) {
            throw new BaseException(SystemCodeEnum.MACHINE_OUT_OF_LENGTH);
        }
        if (item.motor != null && item.motor.length() >= 50) {
            throw new BaseException(SystemCodeEnum.MACHINE_OUT_OF_LENGTH);
        }
    }

    /**
     * 去重校验
     *
     * @param machineInfoList
     * @param type            0新增 1 修改
     * @return
     */
    public List<String> machineDeduplication(List<MachineImportInfo> machineInfoList, Integer type) {
        List<String> mnoList = new LinkedList<>();
        List<String> codeList = new LinkedList<>();
        List<String> frameList = new LinkedList<>();
        List<String> licenseList = new LinkedList<>();
        List<String> motorList = new LinkedList<>();
        for (MachineImportInfo item : machineInfoList) {
            /**长度校验*/
            machineCheck(item);
            mnoList.add(item.machineNO);
            codeList.add(item.userCode);
            if (item.frame != null && !"".equals(item.frame)) {
                frameList.add(item.frame);
            }
            if (item.license != null && !"".equals(item.license)) {
                licenseList.add(item.license);
            }
            if (item.motor != null && !"".equals(item.motor)) {
                motorList.add(item.motor);
            }
        }
        if (mnoList.size() > 0) {
            List<String> mnoResult = mnoList.stream().filter(str -> mnoList.indexOf(str) != mnoList.lastIndexOf(str)).distinct().collect(Collectors.toList());
            List<String> codeResult = codeList.stream().filter(str -> codeList.indexOf(str) != codeList.lastIndexOf(str)).distinct().collect(Collectors.toList());
            List<String> frameResult = frameList.stream().filter(str -> frameList.indexOf(str) != frameList.lastIndexOf(str)).distinct().collect(Collectors.toList());
            List<String> licenseResult = licenseList.stream().filter(str -> licenseList.indexOf(str) != licenseList.lastIndexOf(str)).distinct().collect(Collectors.toList());
            List<String> motorResult = motorList.stream().filter(str -> motorList.indexOf(str) != motorList.lastIndexOf(str)).distinct().collect(Collectors.toList());
            if (!mnoResult.isEmpty() && type == 0) {
                throw new BaseException(SystemCodeEnum.MACHINE_ALREADY_EXIST, JSONObject.toJSONString(mnoResult));
            }
            if (!codeResult.isEmpty()) {
                throw new BaseException(SystemCodeEnum.USERCODE_ALREADY_EXIST, JSONObject.toJSONString(codeResult));
            }
            if (!frameResult.isEmpty()) {
                throw new BaseException(SystemCodeEnum.FRAME_ALREADY_EXIST, JSONObject.toJSONString(frameResult));
            }
            if (!licenseResult.isEmpty()) {
                throw new BaseException(SystemCodeEnum.LICENSE_ALREADY_EXIST, JSONObject.toJSONString(licenseResult));
            }
            if (!motorResult.isEmpty()) {
                throw new BaseException(SystemCodeEnum.MOTOR_ALREADY_EXIST, JSONObject.toJSONString(motorResult));
            }
        }
        // 设备编号是否存在
        List<String> mnoExist = machineDao.cntMachineByMachineNO(mnoList);
        if (!mnoExist.isEmpty() && type == 0) {
            throw new BaseException(SystemCodeEnum.MACHINE_ALREADY_EXIST, JSONObject.toJSONString(mnoExist));
        }
        // 用户码是否存在
        List<String> codeExist = machineDao.cntMachineByUserCode(codeList);
        if (!codeExist.isEmpty() && type == 0) {
            throw new BaseException(SystemCodeEnum.USERCODE_ALREADY_EXIST, JSONObject.toJSONString(codeExist));
        }
        if (!frameList.isEmpty()) {
            List<String> frameExist = machineDao.cntMachineByFrame(frameList);
            if (!frameExist.isEmpty()) {
                throw new BaseException(SystemCodeEnum.FRAME_ALREADY_EXIST, JSONObject.toJSONString(frameExist));
            }
        }
        if (!licenseList.isEmpty()) {
            List<String> licenseExist = machineDao.cntMachineByLicense(licenseList);
            if (!licenseExist.isEmpty()) {
                throw new BaseException(SystemCodeEnum.LICENSE_ALREADY_EXIST, JSONObject.toJSONString(licenseExist));
            }
        }
        if (!motorList.isEmpty()) {
            List<String> motorExist = machineDao.cntMachineByMotor(motorList);
            if (!motorExist.isEmpty()) {
                throw new BaseException(SystemCodeEnum.MOTOR_ALREADY_EXIST, JSONObject.toJSONString(motorExist));
            }
        }
        return mnoList;
    }


    @Override
    @InsertMachineOpLog(machineId = "#machineId", operation = "车辆录入", opType = "删除")
    public void delMachine(LoginInfo info, Integer machineId) {
        Machine machine = machineDao.getByMachineId(machineId);
        if (null != machine) {
            if (!purviewService.purviewCheck(info.id, machine)) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
            machineDao.deleteByPrimaryKey(machineId);
            stockMachineMapper.deleteByMachineId(machineId);
            detentionMachineBoundMapper.deleteByMachineId(machineId);
            mannedService.deleteByMachineId(machineId);
            CompletableFuture.runAsync(() -> publishMachineDeleteEvent(Collections.singletonList(machineId)));
        }
    }

    @Override
    @InsertMachineOpLog(machineId = "#machineId", operation = "中控编号", opType = "变更")
    public void modMachineNO(LoginInfo info, Integer machineId, String machineNO) {
        // 检查是否存在
        Machine machine = machineDao.getByMachineId(machineId);
        if (machine == null) {
            throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
        }

        // 插入车辆操作日志详情
        List<String> logDetail = MachineOpLogDetailHolder.get();
        logDetail.add("变更前编号：" + machine.getMachineNO());
        logDetail.add("变更后编号：" + machineNO);

        // 鉴权
        if (!purviewService.purviewCheck(info.id, machine)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        // 检查新增加的编号是否存在
        Machine newMachine = machineDao.selectByMachineNO(machineNO);
        if (null != newMachine) {
            throw new BaseException(SystemCodeEnum.MACHINE_ALREADY_EXIST);
        }
        // 更新
        Map<String, Object> map = new HashMap<>();
        map.put("machineNO", machineNO);
        map.put("machineId", machineId);
        machineDao.modMachineNO(map);
        /**日志入库*/
        addCodeLog(info, machine, machineNO, machine.getUserCode());
    }

    @Override
    @InsertMachineOpLog(machineId = "#machineId", operation = "车辆编号", opType = "变更")
    public void modUserCode(LoginInfo info, Integer machineId, String userCode, String frame, String license, String motor, String remark) {
        // 检查是否存在
        Machine machine = machineDao.getByMachineId(machineId);
        if (machine == null) {
            throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
        }

        // 插入车辆操作日志详情
        List<String> logDetail = MachineOpLogDetailHolder.get();
        logDetail.add("变更前编号：" + machine.getUserCode());
        logDetail.add("变更后编号：" + userCode);

        // 鉴权
        if (!purviewService.purviewCheck(info.id, machine)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        // 检查新增加的编号是否存在
        Machine newMachine = machineDao.selectByUserCode(userCode);
        if (null != newMachine && !newMachine.getMachineId().equals(machineId)) {
            throw new BaseException(SystemCodeEnum.USERCODE_ALREADY_EXIST);
        }

        // 更新
        Map<String, Object> map = new HashMap<>();
        map.put("userCode", userCode);
        map.put("frame", frame);
        map.put("license", license);
        map.put("motor", motor);
        map.put("machineId", machineId);
        map.put("remark", remark);
        List<Machine> machineNew = machineDao.getExist(map);
        if (machineNew.size() >= 2) {
            throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
        }
        if (machineNew.size() == 1 && !machine.getMachineId().equals(machineNew.get(0).getMachineId())) {
            throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
        }
        machineDao.modUserCode(map);
        //同步修改 回收记录的userCode
        QueryWrapper<RecoveryLog> recoveryLogQueryWrapper = new QueryWrapper<>();
        recoveryLogQueryWrapper.eq("machineId", machineId);
        // 修改满足的machineid的usercode
        RecoveryLog recoveryLog = new RecoveryLog();
        recoveryLog.setUserCode(userCode);
        recoveryLogMapper.update(recoveryLog, recoveryLogQueryWrapper);
        /**日志入库*/
        addCodeLog(info, machine, machine.getMachineNO(), userCode);
    }

    @Override
    public PageData<List<MachineBaseInfo>> searchMachine(LoginInfo info, String accountIds, String key, String machineNOs,
                                                         Integer rowCount, Integer pageNO, Integer machineType, String frame, String license,
                                                         String motor,Integer dataType,String batteryNo,List<Integer> tagIds, Integer machineGroupId, Integer type) {


        if(StrUtil.isNotEmpty(accountIds) && accountIds.contains("-2")){
            return new PageData<>(new LinkedList<>(), 0);
        }
        List<Integer> accountIdList = null;
        if (StrUtil.isNotEmpty(accountIds) && Objects.nonNull(type)) {
            List<String> accountId = Arrays.asList(accountIds.split(","));
            if (1 == type && accountId.size() == 1){
                accountIdList = accountDao.getAccountIdByBrandId(accountId);
            }else if (2 == type){
                accountIdList = accountDao.getAccountIdByFranchiseeId(accountId);
            }else if (3 == type){
                accountIdList = accountId.stream().map(Integer::parseInt).collect(Collectors.toList());
            }
        } else {
            // 非管理就获取一下运营区域列表
            if (!Objects.equals(info.type, UserConstant.USER_ADMIN)) {
                Integer accountUserId = info.getAccountUserId();
                List<Role> roles = roleDao.selectRolePermissionByUserId(accountUserId);
                if (Objects.equals(roles.get(0).getRoleValue(), String.valueOf(UserConstant.USER_CUS_HOLDER))) {
                    accountIdList = holderAccountBoundDao.getByAccountUserId(accountUserId).stream().map(HolderAccountBound::getAccountId).collect(Collectors.toList());
                } else {
                    Account account = accountDao.getByAccountId(info.id);
                    accountIdList = purviewService.getAgentList(account);
                }
                if (accountIds.isEmpty()) {
                    return new PageData<>(new LinkedList<>(), 0);
                }
            }
        }
        // 管理员获取所有，其它身份根据id获取
        Map<String, Object> map = new HashMap<>(16);
        map.put("accountIds", accountIdList);
        map.put("frame", frame);
        map.put("license", license);
        map.put("motor", motor);
        map.put("key", key);
        map.put("machineType", machineType);
        map.put("batteryNo", batteryNo);
        map.put("dataType", dataType);
        map.put("tagIds", tagIds);
        map.put("machineGroupId", machineGroupId);
        map.put("machineNOs", StringUtils.str2Set(machineNOs, ","));
        boolean page = null != rowCount && null != pageNO;
        if (page) {
            map.put("start", rowCount * (pageNO - 1));
            map.put("rowCount", rowCount);
        }
        List<MachineBaseInfo> data = machineDao.searchMachine(map);
        int total = machineDao.cntSearchMachine(map);

        return new PageData<>(data, total);
    }

    @Override
    public List<MachineBaseInfo> exportMachine(LoginInfo info, Integer accountId, String key, String machineNOs, Integer machineType, Integer machineGroupId) {
        List<Integer> accountIds = null;
        if (accountId != null) {
            Account account = accountDao.getByAccountId(accountId);
            Map<String, Object> map = new HashMap<>();
            if (Objects.equals(account.getType(), UserConstant.USER_ADMIN)) {
                // 不加过滤
            } else if (Objects.equals(account.getType(), UserConstant.USER_BRAND)) {
                // 加入pid过滤
                map.put("bid", account.getAccountId());
            } else if (Objects.equals(account.getType(), UserConstant.USER_FRANCHISEE)) {
                // 加入fid过滤
                map.put("fid", account.getAccountId());
            } else if (Objects.equals(account.getType(), UserConstant.USER_AGENT)) {
                // 加入aid过滤
                map.put("aid", account.getAccountId());
            } else {
                return new LinkedList<>();
            }
            List<Account> accounts = accountDao.getAccountTree(map);
            if (!accounts.isEmpty()) {
                accountIds = new ArrayList<>();
                for (Account a : accounts) {
                    if (a.getType().equals(UserConstant.USER_AGENT)) {
                        accountIds.add(a.getAccountId());
                    }
                }
            }
            if (accountIds.isEmpty()) {
                accountIds = null;
            }
        } else {
            // 非管理就获取一下运营区域列表
            if (!Objects.equals(info.type, UserConstant.USER_ADMIN)) {
                Account account = accountDao.getByAccountId(info.id);
                accountIds = purviewService.getAgentList(account);
                if (accountIds.isEmpty()) {
                    return new ArrayList<>();
                }
            }
        }

        Map<String, Object> map = new HashMap<>(8);
        map.put("accountIds", accountIds);
        map.put("key", key);
        map.put("machineType", machineType);
        map.put("machineNOs", StringUtils.str2Set(machineNOs, ","));
        map.put("machineGroupId", machineGroupId);
        List<MachineBaseInfo> data = machineDao.searchMachine(map);
        return data;
    }

    @Override
    public void modMachineStatus(LoginInfo info, List<MachineImportInfo> machineInfoList) {
        List<String> codeList = new LinkedList<>();
        Set<String> codeSet = new HashSet<>();
        Map<Integer, List<String>> stateMap = new HashMap<>();
        for (MachineImportInfo item : machineInfoList) {
            codeList.add(item.userCode);
            codeSet.add(item.userCode);
            if (!stateMap.containsKey(item.bikeState)) {
                stateMap.put(item.bikeState, new LinkedList<>());
            }
            stateMap.get(item.bikeState).add(item.userCode);
        }
        // 用户码是否存在
        List<String> codeExist = machineDao.cntMachineByUserCode(codeList);
        for (String str : codeExist) {
            codeSet.remove(str);
        }
        if (!codeSet.isEmpty()) {
            String[] notExist = new String[codeSet.size()];
            codeSet.toArray(notExist);
            throw new BaseException(SystemCodeEnum.USERCODE_NOT_EXIST, JSONObject.toJSONString(notExist));
        }
        // 鉴权
        User2Machine user2Machine = purviewService.getUser2Machine(info);
        List<String> noRightCode = PurviewHelper.filterNoRightCode(user2Machine, codeExist);
        if (!noRightCode.isEmpty()) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE, JSONObject.toJSONString(noRightCode));
        }
        for (Map.Entry<Integer, List<String>> kv : stateMap.entrySet()) {
            Map<String, Object> map = new HashMap<>();
            map.put("state", kv.getKey());
            map.put("codeList", kv.getValue());
            // 批量修改
            machineDao.batModMachineState(map);
            String opType = kv.getKey().equals(BikeStateConstant.BIKE_STATE_READY_FREE) ? "上架" : "下架";
            List<Machine> machines = machineDao.getByUserCodeList(kv.getValue());
            machineOpLogService.batchAddRecord("车辆投放", opType, true, null, machines);
        }
    }

    @Override
    public Machine getByUserCode(String userCode) {
        return machineDao.selectByUserCode(userCode);
    }

    @Override
    public List<String>
    deleteBatch(List<String> machineNOs) {
        /**不存在设备编号*/
        List<String> notExistMachineNO = new ArrayList<>();
        /**要删除的设备id*/
        List<String> existMachineNO = new ArrayList<>();
        /**要删除的设备id*/
        List<Integer> machineIds = new ArrayList<>();

        /**通过编号查询*/
        List<Machine> machines = getByMachineNOs(machineNOs);

        if (machines.size() > 0) {
            for (Machine machine : machines) {
                machineIds.add(machine.getMachineId());
                existMachineNO.add(machine.getMachineNO());
            }
            /**不存在设备*/
            for (String machineNO : machineNOs) {
                if (!existMachineNO.contains(machineNO)) {
                    notExistMachineNO.add(machineNO);
                }
            }
        } else {
            notExistMachineNO = machineNOs;
        }
        /**删除设备*/
        if (machineIds.size() > 0) {
            Map<String, Object> map = new HashMap<>();
            String machineIdsStr = StringUtil.getListString(machineIds);
            map.put("machineIds", machineIdsStr);
            machineDao.deleteBatch(map);
            mannedService.deleteBatchByMachineId(machineIds);
        }
        return notExistMachineNO;
    }


    @Override
    public List<String> deleteBatchNew(List<String> machineNOs,int dataType,Integer accountId) {
        /**不存在设备编号*/
        List<String> notExistMachineNO = new ArrayList<>();
        /**要删除的设备id*/
        List<String> existMachineNO = new ArrayList<>();
        /**要删除的设备id*/
        List<Integer> machineIds = new ArrayList<>();
        List<Machine> machines = null;
        //0是设备编号,1是用户编号
        if (dataType == 0){
            machines = getByMachineNOs(machineNOs);
        }else {
            machines = getByUserCodes(machineNOs);
        }
        machines = machines.stream().filter(v -> accountId.equals(v.getAccountId())).collect(Collectors.toList());
        if (machines.size() > 0) {
            for (Machine machine : machines) {
                machineIds.add(machine.getMachineId());
                if (dataType == 0){
                    existMachineNO.add(machine.getMachineNO());
                }else {
                    existMachineNO.add(machine.getUserCode());
                }
            }
            /**不存在设备*/
            for (String machineNO : machineNOs) {
                if (!existMachineNO.contains(machineNO)) {
                    notExistMachineNO.add(machineNO);
                }
            }
        } else {
            notExistMachineNO = machineNOs;
        }
        /**删除设备*/
        if (machineIds.size() > 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("machineIds", StringUtil.getListString(machineIds));
            machineDao.deleteBatch(map);

            // 插入车辆操作日志
            machineOpLogService.batchAddRecord("车辆录入", "删除", true, null, machines);

            CompletableFuture.runAsync(() -> publishMachineDeleteEvent(machineIds));
            mannedService.deleteBatchByMachineId(machineIds);
        }
        return notExistMachineNO;
    }

    private void publishMachineDeleteEvent(List<Integer> machineIds) {
        if (CollectionUtil.isNotEmpty(machineIds)) {
            MachineDeleteEvent event = new MachineDeleteEvent(this, machineIds);
            eventPublisher.publishEvent(event);
        }
    }

    @Override
    public void modFrame(LoginInfo info, String userCode, String frame, String license,
                         String motor, String remark) {
        Machine machine = machineDao.getByUserCode(userCode);
        if (machine == null) {
            throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
        }
        if (!purviewService.purviewCheck(info.id, machine)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("userCode", userCode);
        if (frame != null && !"".equals(frame)) {
            map.put("frame", frame);
        }
        if (license != null && !"".equals(license)) {
            map.put("license", license);
        }
        if (motor != null && !"".equals(motor)) {
            map.put("motor", motor);
        }
        if (remark != null && !"".equals(remark)) {
            map.put("remark", remark);
        }
        List<Machine> machineNew = machineDao.getExist(map);
        if (machineNew.size() >= 2) {
            throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
        }
        if (machineNew.size() == 1 && !machine.getMachineId().equals(machineNew.get(0).getMachineId())) {
            throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
        }

        machineDao.modFrame(map);
    }

    @Override
    //@Transactional
    public BatchOperationMsgVO<String> modBatch(LoginInfo info, List<MachineImportInfo> list) {
        List<String> successList = new LinkedList<>();
        List<String> failList = new LinkedList<>();
        List<String> abnormalList = new LinkedList<>();
        for (MachineImportInfo machineImportInfo : list) {
            try {
                if (machineDao.getByUserCode(machineImportInfo.userCode) == null) {
                    abnormalList.add(machineImportInfo.userCode);
                    continue;
                }
                modFrame(info, machineImportInfo.userCode, machineImportInfo.frame, machineImportInfo.license, machineImportInfo.motor, machineImportInfo.remark);
                successList.add(machineImportInfo.userCode);
            } catch (Exception e) {
                failList.add(machineImportInfo.userCode);
            }
        }
        if (true) {
            //后面的暂时去除，改成了部分能修改成功的情况
            BatchOperationMsgVO<String> batchOperationMsgVO = new BatchOperationMsgVO<>();
            batchOperationMsgVO.setSuccessList(successList).setFailList(failList).setAbnormalList(abnormalList);
            return batchOperationMsgVO;
        }
        /**去重校验*/
        machineDeduplication(list, 1);
        for (MachineImportInfo machineImportInfo : list) {
            Machine machine = machineDao.getByUserCode(machineImportInfo.userCode);
            if (machine == null) {
                throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
            }
            if (!purviewService.purviewCheck(info.id, machine)) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
            Map<String, Object> map = new HashMap<>();
            map.put("userCode", machineImportInfo.userCode);
            if (machineImportInfo.frame != null && !"".equals(machineImportInfo.frame)) {
                map.put("frame", machineImportInfo.frame);
            }
            if (machineImportInfo.license != null && !"".equals(machineImportInfo.license)) {
                map.put("license", machineImportInfo.license);
            }
            if (machineImportInfo.motor != null && !"".equals(machineImportInfo.motor)) {
                map.put("motor", machineImportInfo.motor);
            }
            if (machineImportInfo.remark != null && !"".equals(machineImportInfo.remark)) {
                map.put("remark", machineImportInfo.remark);
            }
            List<Machine> machineNew = machineDao.getExist(map);
            if (machineNew.size() >= 2) {
                throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
            }
            if (machineNew.size() == 1 && !machine.getMachineId().equals(machineNew.get(0).getMachineId())) {
                throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
            }
            machineDao.modFrame(map);
        }
        return null;
    }

    /**
     * 添加二码变更日志
     *
     * @param info
     * @param machine
     * @param machineNO
     * @param userCode
     */
    private void addCodeLog(LoginInfo info, Machine machine, String machineNO, String userCode) {
        /**添加绑定日志*/
        AccountUser accountUser = accountUserDao.getAccountUserById(info.accountUserId);
        CodeChangeLog codeChangeLog = new CodeChangeLog();
        codeChangeLog.setAccountId(machine.getAccountId());
        codeChangeLog.setAccountUserId(info.accountUserId);
        codeChangeLog.setAccountUserName(accountUser.getName() == null ? "" : accountUser.getName());
        codeChangeLog.setMachineId(machine.getMachineId());
        codeChangeLog.setNewMachineNO(machineNO);
        codeChangeLog.setNewUserCode(userCode);
        codeChangeLog.setOldMachineNO(machine.getMachineNO());
        codeChangeLog.setOldUserCode(machine.getUserCode());
        codeChangeLog.setRemark("管理系统修改");
        codeChangeLogService.insert(codeChangeLog);
    }


    @Override
    public List<Machine> getByUserCodes(List<String> userCodes) {
        return CollUtil.isEmpty(userCodes) ? Collections.emptyList() : machineDao.getByUserCodeList(userCodes);
    }

    @Override
    public List<Machine> getByAccountIdAndUserCodes(Integer accountId, List<String> userCodes) {
        Map<String, Object> param = new HashMap<>();
        param.put("accountId", accountId);
        param.put("userCodes", StringUtil.getArrayListString(userCodes));
        return machineDao.getByAccountIdAndUserCodes(param);
    }

    @Override
    public List<Machine> getByIds(Set<Integer> ids) {
        return Optional.ofNullable(machineDao.getByIds(ids)).orElse(Collections.emptyList());
    }

    @Override
    public List<Machine> getByBrandIdAndAccountId(Integer brandId, Integer accountId) {
        return Optional.ofNullable(machineDao.getByAccountId(accountId)).orElse(Collections.emptyList());
    }

    @Override
    public List<MachineBaseInfo> loadMachineByPoints(QueryByPointReq req) {
        Integer accountId = req.getAccountId();

        List<MachineStatus> machineStatuses = machineStatusService.getByAccountId(accountId);
        if (CollectionUtil.isEmpty(machineStatuses)) {
            return Collections.emptyList();
        }
        Integer mapType = req.getMapType();
        if (mapType == null) {
            mapType = MapConstant.MAP_GOOGLE;
        }

        //校准点坐标
        List<Point> fixedPoints = new ArrayList<>();
        for (Point point : req.getPoints()) {
            Point fixedPoint = calibrateService.commonCalibrate(point,mapType,MapConstant.MAP_ORI);
            fixedPoints.add(fixedPoint);
        }
        List<String> machineNos = machineStatuses.stream()
                .filter(machineStatus -> judgeMachineInArea(machineStatus, fixedPoints))
                .map(MachineStatus::getMachineNO)
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(machineNos)) {
            return Collections.emptyList();
        }

        Map<String,Object> queryMap = new HashMap<>();
        //确认是品牌还是区域
        queryMap.put("accountIds",Arrays.asList(accountId));
        queryMap.put("machineNOs",machineNos);
        //dataType 0是machineNo,其他则是 userCode
        queryMap.put("dataType",0);
        return machineDao.searchMachine(queryMap);
    }

    @Override
    public Map<String, String> batchMoveMachine(BatchMoveMachineReqVO reqVO) {
        Map<String, String> errResult = new HashMap<>();

        List<String> moveUserCodes = ListUtil.convertList(reqVO.getUserCodes());

        List<Machine> machines = getByUserCodes(moveUserCodes);

        List<String> userCodes = machines.stream().map(Machine::getUserCode).collect(Collectors.toList());

        Map<String, Integer> machineMap = machines.stream().collect(Collectors.toMap(Machine::getUserCode, Machine::getMachineId));

        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());

        // 鉴权
        LoginInfo loginInfo = tokenService.getLoginInfo();
        User2Machine user2Machine = purviewService.getUser2Machine(loginInfo);
        List<String> noRightCode = PurviewHelper.filterNoRightCode(user2Machine, moveUserCodes);
        if (reqVO.getAccountId() != null && !purviewService.purviewCheck(loginInfo.id, reqVO.getAccountId())) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }

        // 骑行中车辆编号
        List<Integer> borrowMachineIds = machineBorrowService.getByMachineIds(machineIds)
                .stream().map(MachineBorrow::getMachineId).collect(Collectors.toList());
        // 占用中车辆编号
        List<Integer> occupyMachineIds = machineOccupyService.getByMachineIds(machineIds)
                .stream().map(MachineOccupy::getMachineId).collect(Collectors.toList());

        List<Integer> moveMachineIds = new ArrayList<>();
        for (String userCode : moveUserCodes) {
            if (!userCodes.contains(userCode)) {
                errResult.put(userCode, "车辆不存在");
                continue;
            }

            if (noRightCode.contains(userCode)) {
                errResult.put(userCode, "无权操作");
                continue;
            }

            Integer machineId = machineMap.get(userCode);

            if (borrowMachineIds.contains(machineId)) {
                errResult.put(userCode, "骑行中");
                continue;
            }

            moveMachineIds.add(machineId);
        }

        if (CollUtil.isNotEmpty(occupyMachineIds)) {
            UQHttpMain.batchUnOccupy(occupyMachineIds, loginInfo.getAccountUserId());
        }

        if (CollUtil.isNotEmpty(moveMachineIds)) {
            machineDao.batchMoveMachine(new BatchMoveMachineBO(StringUtil.getListString(moveMachineIds), reqVO.getAccountId(), reqVO.getState()));
            machineApi.clearMachineStatus(moveMachineIds);
        }

        return errResult;
    }

    private boolean judgeMachineInArea(MachineStatus machineStatus,List<Point> points) {
        if (CollectionUtil.isEmpty(points) || points.size()<3) {
            return false;
        }


        Double x = machineStatus.getLon();
        Double y = machineStatus.getLat();

        if (x == null || y == null) {
            return false;
        }

        return GeoUtil.IsPtInPoly(new Point(x, y), points);
    }

    /**
     * @description: 批量更新车辆信息V2
     * @author: mo.shanyong
     * @date: 2024/9/12 10:10
     * @param: info
     * @param: list
     * @return: com.tbit.uqbike.object.pojo.vo.BatchOperationMsgVO<java.lang.String>
     */
    @Override
    public BatchOperationMsgVO<String> modBatchv2(LoginInfo info, List<MachineImportInfo> list) {
        List<String> successList = new LinkedList<>();
        List<String> failList = new LinkedList<>();
        List<String> abnormalList = new LinkedList<>();
        List<MachineImportInfo> successMachines = new ArrayList<>();
        Map<String, Machine> userCodeMachineMap = new HashMap<>();
        Map<String, Machine> frameMachineMap = new HashMap<>();
        Map<String, Machine> licenseMachineMap = new HashMap<>();
        Map<String, Machine> motorMachineMap = new HashMap<>();
        Set<Integer> machineAIds = new HashSet<>();
        //批量获取车辆信息
        this.getMachines(list,userCodeMachineMap,frameMachineMap,licenseMachineMap,motorMachineMap,machineAIds);
        //检查当前车辆是否是当前账户的
        Map<Integer, Boolean> machineAIdCheckMap = purviewService.purviewCheckV2(info.id, machineAIds);

        list.forEach(machineImportInfo -> {
            try {
                Machine machine = userCodeMachineMap.get(machineImportInfo.userCode);
                if (Objects.isNull(machine)){
                    if (StringUtils.isNotBlank(machineImportInfo.userCode)) {
                        abnormalList.add(machineImportInfo.userCode);
                    }
                }
                else {
                    //获取成功的machine
                    this.getSuccessMachines(machine,machineImportInfo,machineAIdCheckMap,frameMachineMap,licenseMachineMap,
                            motorMachineMap,successMachines,successList);
                }
            }catch (Exception e){
                log.error("e",e);
                failList.add(machineImportInfo.userCode);
            }
        });
        //修改数据库车辆信息
        this.nodMachines(successMachines,successList,failList);

        BatchOperationMsgVO<String> batchOperationMsgVO = new BatchOperationMsgVO<>();
        batchOperationMsgVO.setSuccessList(successList).setFailList(failList).setAbnormalList(abnormalList);
        return batchOperationMsgVO;
    }
    public void getMachines(List<MachineImportInfo> list,
                            Map<String, Machine> userCodeMachineMap,
                            Map<String, Machine> frameMachineMap,
                            Map<String, Machine> licenseMachineMap,
                            Map<String, Machine> motorMachineMap,
                            Set<Integer> machineAIds){
        this.getMachineByMachineInfos(list).forEach(machine -> {
            userCodeMachineMap.put(machine.getUserCode(),machine);
            if (StringUtils.isNotBlank(machine.getFrame())) {
                frameMachineMap.put(machine.getFrame(), machine);
            }
            if (StringUtils.isNotBlank(machine.getLicense())) {
                licenseMachineMap.put(machine.getLicense(), machine);
            }
            if (StringUtils.isNotBlank(machine.getMotor())) {
                motorMachineMap.put(machine.getMotor(), machine);
            }
            machineAIds.add(machine.getAccountId());
        });
    }

    /**
     * @description: 根据车辆的唯一信息(车架号、车牌号、电机号、车辆编号)获取车辆
     * @author: mo.shanyong
     * @date: 2024/9/12 14:09
     * @param: list 车辆信息
     * @return: java.util.List<com.tbit.uqbike.object.pojo.Machine>
     **/
    public List<Machine> getMachineByMachineInfos(List<MachineImportInfo> list){
        List<String> userCodeList = new ArrayList<>();
        List<String> frameList = new ArrayList<>();
        List<String> licenseList = new ArrayList<>();
        List<String> motorList = new ArrayList<>();
        list.forEach(machineImportInfo -> {
            if (StringUtils.isNotBlank(machineImportInfo.userCode)){
                userCodeList.add(machineImportInfo.userCode);
            }
            if (StringUtils.isNotBlank(machineImportInfo.frame)){
                frameList.add(machineImportInfo.frame);
            }
            if (StringUtils.isNotBlank(machineImportInfo.license)){
                licenseList.add(machineImportInfo.license);
            }
            if (StringUtils.isNotBlank(machineImportInfo.motor)){
                motorList.add(machineImportInfo.motor);
            }
        });
        //分数据获取
        return machineDao.getMachinesByMachineInfos(userCodeList,frameList,frameList,frameList);
    }

    /**
     * @description: 获取可以成功去更新的车辆
     * @author: mo.shanyong
     * @date: 2024/9/14 11:03
     * @param: machine
     * @param: machineImportInfo
     * @param: machineAIdCheckMap
     * @param: frameMachineMap
     * @param: licenseMachineMap
     * @param: motorMachineMap
     * @param: successMachines
     * @param: successList
     **/
    public void getSuccessMachines(Machine machine,
                                   MachineImportInfo machineImportInfo,
                                   Map<Integer, Boolean> machineAIdCheckMap,
                                   Map<String, Machine> frameMachineMap,
                                   Map<String, Machine> licenseMachineMap,
                                   Map<String, Machine> motorMachineMap,
                                   List<MachineImportInfo> successMachines,
                                   List<String> successList){
        Boolean purviewCheck = machineAIdCheckMap.get(machine.getAccountId());
        if (Objects.isNull(purviewCheck) || !purviewCheck){
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        //检查是否存在重复车辆
        this.checkMachine(machine,frameMachineMap.get(machineImportInfo.frame),
                licenseMachineMap.get(machineImportInfo.license),
                motorMachineMap.get(machineImportInfo.motor));
        successList.add(machineImportInfo.userCode);
        successMachines.add(machineImportInfo);
    }

    /**
     * @description:检查是否有重复机器
     * @author: mo.shanyong
     * @date: 2024/9/12 14:27
     * @param: machine 使用userCode查出来的machine
     * @param: frameMachine
     * @param: licenseMachine
     * @param: motorMachine
     **/
    public void checkMachine(Machine machine,
                             Machine frameMachine,
                             Machine licenseMachine,
                             Machine motorMachine){
        if ((Objects.nonNull(frameMachine) && !Objects.equals(machine.getMachineId(),frameMachine.getMachineId())) ||
                (Objects.nonNull(licenseMachine) && !Objects.equals(machine.getMachineId(),licenseMachine.getMachineId())) ||
                (Objects.nonNull(motorMachine) && !Objects.equals(machine.getMachineId(),motorMachine.getMachineId()))
        ){
            throw new BaseException(SystemCodeEnum.NO_ALREADY_EXIST);
        }

    }

    /**
     * @description: 批量更新数据库车辆信息
     * @author: mo.shanyong
     * @date: 2024/9/14 11:04
     * @param: successMachines 上一步获取到的可以去更新的车辆
     * @param: successList 存放更新成功的车辆编号
     * @param: failList 失败车辆编号
     **/
    public void nodMachines(List<MachineImportInfo> successMachines,
                            List<String> successList,
                            List<String> failList){
        if (CollectionUtil.isEmpty(successMachines))
            return;

        if (CollectionUtil.isNotEmpty(successMachines)){
            try {
                List<List<MachineImportInfo>> parList = Lists.partition(successMachines, 1000);
                for (List<MachineImportInfo> machineImportInfos : parList) {
                    machineDao.updateMachines(machineImportInfos);
                }
            }catch (Exception e){
                log.info("e",e);
                failList.addAll(successList);
                successList.clear();
            }
        }
    }

    /**
     * @description: 获取车辆列表
     * @author: mo.shanyong
     * @date: 2024/11/28 14:30
     * @param: machineSearchDTO 搜索参数
     * @return: com.tbit.uqbike.object.business.PageData<java.util.List < com.tbit.uqbike.object.pojo.MachineBaseInfo>>
     */
    @Override
    public PageData<List<MachineBaseInfo>> searchMachineV2(MachineSearchDTO machineSearchDTO) {
        List<Integer> accountIdList = null;
        String accountIds = machineSearchDTO.getAccountIds();
        Integer type = machineSearchDTO.getType();
        if (StrUtil.isNotEmpty(accountIds) && Objects.nonNull(type)) {
            List<String> accountId = Arrays.asList(accountIds.split(","));
            if (1 == type && accountId.size() == 1){
                accountIdList = accountDao.getAccountIdByBrandId(accountId);
            }else if (2 == type){
                accountIdList = accountDao.getAccountIdByFranchiseeId(accountId);
            }else if (3 == type){
                accountIdList = accountId.stream().map(Integer::parseInt).collect(Collectors.toList());
            }
        } else {
            LoginInfo info = machineSearchDTO.getInfo();
            // 非管理就获取一下运营区域列表
            if (!Objects.equals(info.type, UserConstant.USER_ADMIN)) {
                Integer accountUserId = info.getAccountUserId();
                List<Role> roles = roleDao.selectRolePermissionByUserId(accountUserId);
                if (Objects.equals(roles.get(0).getRoleValue(), String.valueOf(UserConstant.USER_CUS_HOLDER))) {
                    accountIdList = holderAccountBoundDao.getByAccountUserId(accountUserId).stream().map(HolderAccountBound::getAccountId).collect(Collectors.toList());
                } else {
                    Account account = accountDao.getByAccountId(info.id);
                    accountIdList = purviewService.getAgentList(account);
                }
                if (accountIds.isEmpty()) {
                    return new PageData<>(new LinkedList<>(), 0);
                }
            }
        }
        // 管理员获取所有，其它身份根据id获取
        machineSearchDTO.setStart((machineSearchDTO.getPageNO() - 1) * machineSearchDTO.getRowCount());
        machineSearchDTO.setAccountIdList(accountIdList);
        List<MachineBaseInfo> data = machineDao.searchMachineV2(machineSearchDTO);
        int total = machineDao.cntSearchMachineV2(machineSearchDTO);
        return new PageData<>(data, total);
    }


    /**
     * 批量操作sim提醒状态
     * @param dto dto
     * @return Result<Object>
     */
    @Override
    public Result<Object> updateRemindState(MachineRemindDTO dto) {

        if (dto.getUserCodeOrMachineNo().size() > 1000){
            return Result.error("最多只能操作1000条");
        }

        /*查询对应区域下的编号*/
        List<String> noList = machineDao.selectByAccountId(dto.getAccountId(), dto.getType(), dto.getUserCodeOrMachineNo());

        if (CollectionUtil.isNotEmpty(noList)) {
            /*批量修改提醒状态*/
            machineDao.updateRemindState(noList, dto.getOperateType(), dto.getType());
        }

        List<RemindStateVO> failList = dto.getUserCodeOrMachineNo().stream()
                .filter(no -> !noList.contains(no))
                .map(no -> new RemindStateVO(dto.getType(), no, "编号不存在"))
                .collect(Collectors.toList());

        return Result.success(failList);
    }
}
